<?php
/* 预约日期和时间段相关操作控制器 */

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;

class DateSlotController extends HomeController
{
    public function __construct(Request $request)
    {
        parent::__construct('generate');
    }

    //生成具体的可预约日期和时间段
    public function generate(Request $request)
    {
        try {
            //查询含有当前日期且生效状态的预约规则
            $current_date = date('Y-m-d');
            $set = DB::table('reservation_set')->where('start_date', '<=', $current_date)->where('end_date', '>=', $current_date)->where('status', 1)->first();

            $time_arr1 = [];
            $date_arr1 = [];
            //判断上午有没有闭馆时间
            if ($set->am_end_time) {
                //有闭馆时间，先生成上午的预约时间段
                $time_arr1 = $this->get_time_slot_by_time($set->am_start_time, $set->am_end_time, $set->slot_length);
                //判断有没有下午的开馆闭馆时间
                if ($set->pm_start_time && $set->pm_end_time) {
                    $pm_arr = $this->get_time_slot_by_time($set->pm_start_time, $set->pm_end_time, $set->slot_length);
                    $time_arr1 = array_merge($time_arr1, $pm_arr);
                }
            } else {
                //没有上午闭馆时间，即中午不休息，则直接生成全天预约时间段
                $time_arr1 = $this->get_time_slot_by_time($set->am_start_time, $set->pm_end_time, $set->slot_length);
            }

            //根据当前日期和最大提前预约天数，计算出最大预约日期，包含当天，因此要减1天
            $max_lead = $set->max_lead - 1;
            $max_date = date('Y-m-d', strtotime("+ $max_lead days"));
            //如果最大预约日期大于预约规则的结束日期，则最大预约日期为预约规则的结束日期
            if ($max_date > $set->end_date) {
                $max_date = $set->end_date;

                //时间转换为时间戳,，只写日期不写时间，时间默认是00:00:00
                $date1 = strtotime(date('Y-m-d'));
                $date2 = strtotime($max_date . ' 23:59:59');
                
                //时间戳相减，得到的是秒数，再除以一天的秒数，得到的是可提前预约天数，使用ceil函数，向上取整
                $date = ceil(($date2 - $date1) / 3600 / 24);
                for ($m = 0; $m < $date; $m++) {
                    $date_arr1[] = date('Y-m-d', strtotime("+ $m days"));
                }
                //调用函数添加数据到数据表
                $this->insert_date_slot($date_arr1, $time_arr1, $set);



                $start_date2 = date('Y-m-d', strtotime("+ $date days"));
                //根据第二次的开始日期查询预约规则
                $set2 = DB::table('reservation_set')->where('start_date', '>=', $start_date2)->where('status', 1)->first();

                $time_arr2 = [];
                //判断上午有没有闭馆时间
                if ($set2->am_end_time) {
                    //有闭馆时间，先生成上午的预约时间段
                    $time_arr2 = $this->get_time_slot_by_time($set2->am_start_time, $set2->am_end_time, $set2->slot_length);
                    //判断有没有下午的开馆闭馆时间
                    if ($set2->pm_start_time && $set2->pm_end_time) {
                        $pm_arr2 = $this->get_time_slot_by_time($set2->pm_start_time, $set2->pm_end_time, $set2->slot_length);
                        $time_arr2 = array_merge($time_arr2, $pm_arr2);
                    }
                } else {
                    //没有上午闭馆时间，即中午不休息，则直接生成全天预约时间段
                    $time_arr2 = $this->get_time_slot_by_time($set2->am_start_time, $set2->pm_end_time, $set2->slot_length);
                }

                $date2 = $set2->max_lead - $date;
                $date_arr2 = [];
                //从上个规则的结束日期开始，循环得到日期数组
                for ($n = $date; $n < $set2->max_lead; $n++) {
                    $date_arr2[] = date('Y-m-d', strtotime("+ $n days"));
                }
                //调用函数添加数据到数据表
                $this->insert_date_slot($date_arr2, $time_arr2, $set2);


            } else {
                //只有一个规则，则直接根据最大预约天数，生成日期数组
                //循环得到日期数组
                for ($m = 0; $m < $set->max_lead; $m++) {
                    $date_arr1[] = date('Y-m-d', strtotime("+ $m days"));
                }
                //调用函数添加数据到数据表
                $this->insert_date_slot($date_arr1, $time_arr1, $set);
            }

        } catch (\Exception $e) {
            // 记录错误日志
            Log::error('获取公告列表失败: ' . $e->getMessage());
            return response()->json([
                'code' => 500,
                'message' => '获取公告列表失败',
                'data' => null
            ]);
        }
    }


    //根据日期数组和时间段数组，批量插入预约时间段
    public function insert_date_slot ($date_arr, $time_arr, $set)
    {
        foreach ($date_arr as $date) {
            foreach ($time_arr as $time) {
                $data = [
                    'set_id' => $set->id,
                    'date' => $date,
                    'start_time' => $time['start_time'],
                    'end_time' => $time['end_time'],
                    'max_capacity' => $set->max_capacity,
                ];
                DB::table('date_slot')->insert($data);
            }
        }
    }





    //根据时间范围获取预约时间段
    public function get_time_slot_by_time ($time1, $time2, $slot_length)
    {
        $time_arr = [];
        //时间转换为时间戳
        $time_stamp1 = strtotime($time1);
        $time_stamp2 = strtotime($time2);
        //把时间间隔从分钟转换为秒
        $slot_length = $slot_length * 60;

        //时间戳相减，得到的是秒数，再除以预约时间间隔，得到的是预约次数，使用ceil函数，向上取整，确保预约次数不会少
        $times = ceil(($time_stamp2 - $time_stamp1) / $slot_length);
        //遍历次数，生成预约时间段
        for ($i = 0; $i < $times; $i++) {
            if ($i + 1 == $times) {
                //最后一次的时间段，为了避免除不尽，所以直接取闭馆时间
                $time_arr[] = [
                    'start_time' => date('H:i:s', $time_stamp1 + $i * $slot_length),
                    'end_time' => $time2,
                ];
            } else {
                $time_arr[] = [
                    'start_time' => date('H:i:s', $time_stamp1 + $i * $slot_length),
                    'end_time' => date('H:i:s', $time_stamp1 + ($i + 1) * $slot_length),
                ];
            }
        }
        return $time_arr;

    }

    

    

}
